
package com.studiofortress.sf.structure.collisions;

import com.studiofortress.sf.structure.Action;
import com.studiofortress.sf.structure.Actor;
import java.util.Collection;

/**
 * The standard interface that any internal CollisionStructure class must adhere
 * too. Ideally for the remove, update, 
 * 
 * @author Joseph Lenton
 */
public interface CollisionHandler<A extends Actor>
{
    /**
     * @param actor For adding or associating this Actor wiht the CollisionStructure.
     */
    abstract void add(A actor);
    
    /**
     * @param actor Remove this Actor from the CollisionStructures collision detection.
     */
    abstract void remove(A actor);
    
    /**
     * This should be expected to be called when an Actor that is already within
     * within this Collision Structure is moved or resized.
     * @param actor The Actor to update inside the collision structure.
     */
    abstract void update(A actor);
    
    /**
     * @param actor The Actor the collision detection is centred around, does not already need to be in this CollisionStructure.
     * @param collisionClasses The classes of Actor that the given Actor is being checked against.
     * @return A list of all Actors that collide with this Actor and are of one of the given classes.
     */
    abstract Collection<A> getIntersectingActors(A actor, Class<? extends A> ... collisionClasses);
    
    /**
     * Very similar to getIntersectingActors except this returns a single Actor
     * that collidss with the given Actor.
     * @param actor The Actor collision detection is being checked with, does not need to already be in the CollisionStructure.
     * @param collisionClasses The classes of Actor the given Actor is to be checked against.
     * @return Any Actor which is an instance of one of the given class that is found to intersect the given Actor.
     */
    abstract A getIntersectingActor(A actor, Class<? extends A> ... collisionClasses);

    /**
     * Applies the given collision action to all the actors of the given classes
     * that collides with the given actor.
     * @param actor The actor at the centre of the collision, to check against other actor for an intersection.
     * @param action The action to perform on any actors that intersect the given actor.
     * @param collisionClasses The type of actors to check for, or null to check for all.
     * @return True if actors were found and the action was performed on them, otherwise false if no actors were found.
     */
    abstract boolean applyToIntersectingActors(A actor, Action<A> action, Class<? extends A> ... collisionClasses);

    /**
     * Applies the given collision action to the first actor found that
     * intersects the given actor.
     *
     * If multiple actors intersect with the given actor, then there is no
     * guarantee that the first actor found is always the same in subsequent
     * calls to this method.
     * @param actor The actor at the centre of the collision, to check against other actor for an intersection.
     * @param action The action to perform on any actors that intersect the given actor.
     * @param collisionClasses The type of actors to check for, or null to check for all.
     * @return True if an actor was found and the action was performed on it, otherwise false.
     */
    abstract boolean applyToIntersectingActor(A actor, Action<A> action, Class<? extends A> ... collisionClasses);
}
